const express = require('express');
const router = express.Router();
const { exec } = require('child_process');
const util = require('util');
const { verifyAdmin } = require('../middleware/auth');

const execPromise = util.promisify(exec);

// 应用定义
const APPS = {
  // Web服务器
  nginx: {
    name: 'Nginx',
    category: 'web',
    description: '高性能Web服务器和反向代理',
    installCommand: 'apt-get update && apt-get install -y nginx',
    uninstallCommand: 'apt-get remove -y nginx',
    serviceCommand: 'systemctl {action} nginx',
    detectCommand: 'which nginx',
    ports: [80, 443],
    configFiles: ['/etc/nginx/nginx.conf'],
    dataDir: ['/var/www/html']
  },
  apache: {
    name: 'Apache',
    category: 'web',
    description: '流行的Web服务器',
    installCommand: 'apt-get update && apt-get install -y apache2',
    uninstallCommand: 'apt-get remove -y apache2',
    serviceCommand: 'systemctl {action} apache2',
    detectCommand: 'which apache2ctl',
    ports: [80, 443],
    configFiles: ['/etc/apache2/apache2.conf'],
    dataDir: ['/var/www/html']
  },
  
  // 数据库
  mysql: {
    name: 'MySQL',
    category: 'database',
    description: '流行的关系型数据库',
    installCommand: 'apt-get update && apt-get install -y mysql-server',
    uninstallCommand: 'apt-get remove -y mysql-server',
    serviceCommand: 'systemctl {action} mysql',
    detectCommand: 'which mysql',
    ports: [3306],
    configFiles: ['/etc/mysql/my.cnf'],
    dataDir: ['/var/lib/mysql']
  },
  mariadb: {
    name: 'MariaDB',
    category: 'database',
    description: 'MySQL的开源分支',
    installCommand: 'apt-get update && apt-get install -y mariadb-server',
    uninstallCommand: 'apt-get remove -y mariadb-server',
    serviceCommand: 'systemctl {action} mariadb',
    detectCommand: 'which mariadb',
    ports: [3306],
    configFiles: ['/etc/mysql/mariadb.conf.d/50-server.cnf'],
    dataDir: ['/var/lib/mysql']
  },
  mongodb: {
    name: 'MongoDB',
    category: 'database',
    description: '流行的NoSQL数据库',
    installCommand: 'apt-get update && apt-get install -y mongodb',
    uninstallCommand: 'apt-get remove -y mongodb',
    serviceCommand: 'systemctl {action} mongodb',
    detectCommand: 'which mongod',
    ports: [27017],
    configFiles: ['/etc/mongodb.conf'],
    dataDir: ['/var/lib/mongodb']
  },
  
  // 语言运行时
  php: {
    name: 'PHP',
    category: 'language',
    description: '流行的服务端脚本语言',
    installCommand: 'apt-get update && apt-get install -y php-fpm php-mysql',
    uninstallCommand: 'apt-get remove -y php-fpm php-mysql',
    serviceCommand: 'systemctl {action} php7.4-fpm',
    detectCommand: 'which php',
    configFiles: ['/etc/php/7.4/fpm/php.ini'],
    dataDir: []
  },
  nodejs: {
    name: 'Node.js',
    category: 'language',
    description: 'JavaScript运行时环境',
    installCommand: 'apt-get update && apt-get install -y nodejs npm',
    uninstallCommand: 'apt-get remove -y nodejs npm',
    detectCommand: 'which node',
    configFiles: [],
    dataDir: []
  },
  
  // 缓存和队列
  redis: {
    name: 'Redis',
    category: 'cache',
    description: '内存数据结构存储，可用作数据库、缓存和消息代理',
    installCommand: 'apt-get update && apt-get install -y redis-server',
    uninstallCommand: 'apt-get remove -y redis-server',
    serviceCommand: 'systemctl {action} redis-server',
    detectCommand: 'which redis-server',
    ports: [6379],
    configFiles: ['/etc/redis/redis.conf'],
    dataDir: ['/var/lib/redis']
  },
  
  // 安全工具
  fail2ban: {
    name: 'Fail2Ban',
    category: 'security',
    description: '防止暴力破解的入侵检测系统',
    installCommand: 'apt-get update && apt-get install -y fail2ban',
    uninstallCommand: 'apt-get remove -y fail2ban',
    serviceCommand: 'systemctl {action} fail2ban',
    detectCommand: 'which fail2ban-client',
    configFiles: ['/etc/fail2ban/jail.conf'],
    dataDir: []
  }
};

/**
 * @route   GET /api/app/list
 * @desc    获取应用列表
 * @access  私有
 */
router.get('/list', async (req, res) => {
  try {
    const appList = [];
    
    for (const [id, app] of Object.entries(APPS)) {
      // 检查应用是否已安装
      let installed = false;
      let running = false;
      
      try {
        await execPromise(app.detectCommand);
        installed = true;
        
        // 如果有服务命令，检查服务是否运行
        if (app.serviceCommand) {
          const serviceCommand = app.serviceCommand.replace('{action}', 'status');
          try {
            const { stdout } = await execPromise(serviceCommand);
            running = stdout.includes('active (running)');
          } catch (error) {
            // 服务可能未运行
          }
        }
      } catch (error) {
        // 应用未安装
      }
      
      appList.push({
        id,
        ...app,
        installed,
        running
      });
    }
    
    // 按分类分组
    const groupedApps = {};
    
    appList.forEach(app => {
      const category = app.category || 'other';
      if (!groupedApps[category]) {
        groupedApps[category] = [];
      }
      groupedApps[category].push(app);
    });
    
    res.json(groupedApps);
  } catch (error) {
    res.status(500).json({ error: `获取应用列表失败: ${error.message}` });
  }
});

/**
 * @route   POST /api/app/install/:id
 * @desc    安装应用
 * @access  私有 (仅管理员)
 */
router.post('/install/:id', verifyAdmin, async (req, res) => {
  try {
    const { id } = req.params;
    const app = APPS[id];
    
    if (!app) {
      return res.status(404).json({ error: '应用不存在' });
    }
    
    // 检查应用是否已安装
    try {
      await execPromise(app.detectCommand);
      return res.status(400).json({ error: '应用已安装' });
    } catch (error) {
      // 应用未安装，继续
    }
    
    // 安装应用
    const { stdout, stderr } = await execPromise(app.installCommand);
    
    res.json({
      message: `${app.name} 安装成功`,
      details: stdout
    });
  } catch (error) {
    res.status(500).json({ error: `安装失败: ${error.message}` });
  }
});

/**
 * @route   POST /api/app/uninstall/:id
 * @desc    卸载应用
 * @access  私有 (仅管理员)
 */
router.post('/uninstall/:id', verifyAdmin, async (req, res) => {
  try {
    const { id } = req.params;
    const app = APPS[id];
    
    if (!app) {
      return res.status(404).json({ error: '应用不存在' });
    }
    
    // 检查应用是否已安装
    try {
      await execPromise(app.detectCommand);
    } catch (error) {
      return res.status(400).json({ error: '应用未安装' });
    }
    
    // 卸载应用
    const { stdout, stderr } = await execPromise(app.uninstallCommand);
    
    res.json({
      message: `${app.name} 卸载成功`,
      details: stdout
    });
  } catch (error) {
    res.status(500).json({ error: `卸载失败: ${error.message}` });
  }
});

/**
 * @route   POST /api/app/action/:id
 * @desc    执行应用操作（启动/停止/重启）
 * @access  私有 (仅管理员)
 */
router.post('/action/:id', verifyAdmin, async (req, res) => {
  try {
    const { id } = req.params;
    const { action } = req.body;
    const app = APPS[id];
    
    if (!app) {
      return res.status(404).json({ error: '应用不存在' });
    }
    
    if (!action) {
      return res.status(400).json({ error: '未指定操作类型' });
    }
    
    if (!['start', 'stop', 'restart', 'status'].includes(action)) {
      return res.status(400).json({ error: '无效的操作类型' });
    }
    
    if (!app.serviceCommand) {
      return res.status(400).json({ error: '此应用不支持服务操作' });
    }
    
    // 执行服务操作
    const command = app.serviceCommand.replace('{action}', action);
    await execPromise(command);
    
    res.json({
      message: `${app.name} ${
        action === 'start' ? '已启动' : 
        action === 'stop' ? '已停止' : 
        action === 'restart' ? '已重启' : 
        '状态已更新'
      }`
    });
  } catch (error) {
    res.status(500).json({ error: `操作失败: ${error.message}` });
  }
});

/**
 * @route   GET /api/app/info/:id
 * @desc    获取应用详细信息
 * @access  私有
 */
router.get('/info/:id', async (req, res) => {
  try {
    const { id } = req.params;
    const app = APPS[id];
    
    if (!app) {
      return res.status(404).json({ error: '应用不存在' });
    }
    
    // 检查应用是否已安装
    let installed = false;
    let running = false;
    let version = '';
    
    try {
      await execPromise(app.detectCommand);
      installed = true;
      
      // 尝试获取版本信息
      try {
        const { stdout } = await execPromise(`${app.detectCommand.split(' ')[0]} --version`);
        const versionMatch = stdout.match(/(\d+\.\d+\.\d+)/);
        version = versionMatch ? versionMatch[1] : '';
      } catch (error) {
        // 无法获取版本信息
      }
      
      // 如果有服务命令，检查服务是否运行
      if (app.serviceCommand) {
        const serviceCommand = app.serviceCommand.replace('{action}', 'status');
        try {
          const { stdout } = await execPromise(serviceCommand);
          running = stdout.includes('active (running)');
        } catch (error) {
          // 服务可能未运行
        }
      }
    } catch (error) {
      // 应用未安装
    }
    
    res.json({
      id,
      ...app,
      installed,
      running,
      version
    });
  } catch (error) {
    res.status(500).json({ error: `获取应用信息失败: ${error.message}` });
  }
});

module.exports = router;